Skip to content

fix: reconcile routeselected handlers and persist selected alternative#489

Merged
DennisOSRM merged 4 commits into
gh-pagesfrom
reconcile-routeselected-handlers
Jul 4, 2026
Merged

fix: reconcile routeselected handlers and persist selected alternative#489
DennisOSRM merged 4 commits into
gh-pagesfrom
reconcile-routeselected-handlers

Conversation

@DennisOSRM

@DennisOSRM DennisOSRM commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #455 — merges two separate lrmControl.on('routeselected') listeners into a single handler and fixes a bug where the selected route alternative was never persisted to the URL.

Problem

  1. Duplicate listeners — state.js and index.js each registered a routeselected listener on the same LRM control, doubling dispatch work and making the event flow harder to reason about.
  2. Alternative never persisted — The state.js listener set this.options.alternative but never called this.update(), so the selected alternative was lost on reload.
  3. LRM always selects route[0] — On initial load, the LRM selects the first route, which would overwrite any ?alt=N URL parameter before it could be persisted.

Changes

File Change
src/state.js Removed the routeselected listener
src/index.js Merged handler: tracks alternative + calls state.update(), switches to URL-specified alternative on initial load
src/route_alternative.js New — pure function resolveInitialAlternative() with fallback logic
test/route_alternative.test.js New — 18 unit tests

Behavior

  • Load with ?alt=2: selects and persists alternative 2
  • Load with ?alt=5 but only 3 alternatives exist: falls back to route 0
  • User clicks an alternative: persists to URL via replaceState (no history entry)
  • User changes waypoints: re-applies previously selected alternative (or falls back)

AI assistance: Claude Code helped with extracting the pure helper, writing test cases, and structuring the PR.

Merge two separate lrmControl.on('routeselected') listeners into a single
handler in index.js. The state.js listener only set
this.options.alternative but never called this.update(), so the selected
alternative was never persisted to the URL.

Changes:
- Remove routeselected listener from state.js
- Add alternative tracking + state.update() to the remaining handler
- Switch to URL-specified alternative on initial load (LRM always
  selects route[0] first), with fallback if the alternative no longer
  exists
- Extract alternative-resolution logic into pure
  resolveInitialAlternative() in src/route_alternative.js
- Add 18 unit tests covering no-switch, switch, fallback, and edge cases

Closes #455

Co-Authored-By: Claude <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 4, 2026 15:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses #455 by consolidating routeselected handling into src/index.js and ensuring the selected route alternative is persisted into (and restored from) URL state, including a first-load switch away from LRM’s default route[0] when ?alt=N is present.

Changes:

  • Remove the duplicate routeselected listener from src/state.js to avoid double-dispatch and diverging behavior.
  • Add first-load alternative resolution + URL persistence for selected alternatives in src/index.js.
  • Introduce src/route_alternative.js with accompanying Jest tests to determine when/how to switch to a URL-specified alternative.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
src/state.js Removes redundant routeselected listener so alternative selection is handled in one place.
src/index.js Centralizes routeselected logic: resolves initial alternative from URL and persists selected alternative via state.update().
src/route_alternative.js Adds helper to decide whether to re-fire routeselected for a URL-requested alternative.
test/route_alternative.test.js Adds unit coverage for initial-alternative resolution behavior and edge cases.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/route_alternative.js
Comment on lines +19 to +21
var index = Number(desiredAlt);
if (!index || index < 0) return null; // 0, NaN, undefined, null, "", negative
if (route.routesIndex === index) return null; // already on the desired route

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Added index % 1 !== 0 to the guard clause so non-integer values like 1.5 (or the string "1.5") are rejected before they reach the array index lookup. This covers floats and Infinity, and works across all JS environments (unlike Number.isInteger).

Comment on lines +81 to +86
test('desiredAlt is negative', function() {
var route = makeRoute(0);
var result = resolveInitialAlternative(route, [makeRoute(1)], -1);
expect(result).toBeNull();
});
});

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added two regression tests: one for a float literal 1.5 and one for a float string "1.5" — both now correctly return null.

github-actions Bot added 3 commits July 4, 2026 18:00
…ve resolution

Non-integer values like 1.5 (which could come from URL query strings)
would produce allRoutes[1.5] = undefined, causing an undefined route
payload and potential re-entrant routeselected firing. Add index % 1 !== 0
guard and regression tests for float and float-string inputs.
Prohibit cute/whimsical names; require descriptive, functional names
for variables and functions.
@DennisOSRM DennisOSRM merged commit 3b3b0e8 into gh-pages Jul 4, 2026
5 checks passed
@DennisOSRM DennisOSRM deleted the reconcile-routeselected-handlers branch July 4, 2026 16:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

reconcile routeselected handlers

2 participants